<template>
  <el-card class="box-card card-header">
    <div slot="header" class="clearfix f-medium">
      <i class="fa fa-map m-r-10 text-c-blue" aria-hidden="true"></i>
      <span>定位电子地图</span>
    </div>
    <div class="mapView">
      <div class="map-view">
        <ZMap ref="zmap" :initConfig="initConfig">
          <template #footer="{ clear }">
            <div class="text-center m-t-10">
              <el-button plain @click="clear">清除所有标记</el-button>
              <el-button type="info" plain @click="addRegionalDialog = true"><i class="fa fa-database"
                  aria-hidden="true"></i></el-button>
              <el-button type="primary" plain @click="addDpDialog = true">无线传感网络</el-button>
            </div>
          </template>
        </ZMap>
      </div>
      <!-- 显示当前无人船坐标的视窗 -->
      <div class="lngLatBox text-center">
        <span class="f-w-400">
          <i class="fa fa-map-marker-alt text-c-green"></i> 无人船GPS位置
        </span>
        <div class="text-c-blue flex-row-around">
          <span>{{ position.lng }}°E</span>
          <span>-</span>
          <span>{{ position.lat }}°N</span>
        </div>
      </div>
    </div>
    <!-- 添加无线传感网络的弹窗 -->
    <el-dialog title="修改无线传感网络坐标" :visible.sync="addDpDialog" width="500px">
      <div class="text-center" style="height: 100px">
        <img src="@/assets/icon/locationNetwork.svg" alt="" height="100%" />
      </div>
      <el-row :gutter="20" class="m-t-20">
        <el-col :span="12"><el-input v-model="sensor.lng" placeholder="请输入经度(0~180°)"
            :oninput="checkLng(sensor, 'lng')"></el-input></el-col>
        <el-col :span="12"><el-input v-model="sensor.lat" placeholder="请输入纬度(0~90°)"
            :oninput="checkLat(sensor, 'lat')"></el-input></el-col>
      </el-row>
      <span slot="footer" class="dialog-footer">
        <el-button type="primary" @click="addDPMarker">添加</el-button>
      </span>
    </el-dialog>
    <!-- 添加水质区域分布数据弹窗 -->
    <el-dialog title="水质区域分布数据上传" :visible.sync="addRegionalDialog" width="500px">
      <div class="flex-row-center m-b-10" v-for="(item, index) in regionalInput">
        <el-row :gutter="10">
          <el-col :span="2" class="text-center f-w-700">
            <el-tag>{{ index + 1 }}</el-tag>
          </el-col>
          <el-col :span="9">
            <el-input type="number" v-model="item.lng" placeholder="经度" size="small"></el-input>
          </el-col>
          <el-col :span="9">
            <el-input type="number" v-model="item.lat" placeholder="纬度" size="small"></el-input>
          </el-col>
          <el-col :span="4">
            <el-input type="number" v-model="item.count" placeholder="指数" size="small"></el-input>
          </el-col>
        </el-row>
      </div>
      <span slot="footer" class="dialog-footer">
        <el-button type="primary" @click="addRegional">添加</el-button>
      </span>
    </el-dialog>
  </el-card>
</template>

<script>
var a = 0.0001
// 引入地图加载器
import { getShipPosition } from "@/api/cruiseMange";
import { getSensorLocation, updateSensorLocation } from "@/api/planManage";
import { insertPointQualitys } from "@/api/waterAnalysis";
import { mapState } from "vuex";
import { initConfig } from '../config/map-config'
import checkLngLat from "@/mixins/checkLngLat";
export default {
  name: "EMap",
  mixins: [checkLngLat],
  data() {
    return {
      initConfig,
      addDpDialog: false,
      addRegionalDialog: false,
      sensor: {
        lng: "",
        lat: "",
      },
      position: {
        lng: "- - -", //经度
        lat: "- - -", //纬度
      },
      regionalInput: [
        {
          count: '',
          lat: '',
          lng: '',
        },
        {
          count: '',
          lat: '',
          lng: '',
        },
        {
          count: '',
          lat: '',
          lng: '',
        },
        {
          count: '',
          lat: '',
          lng: '',
        }
      ],
      timeId: null,
      // 定义标记覆盖物当前计数，用于确定点的是第几个点生成标记
      MarkerIndex: "",
      followPath: [],
    };
  },
  mounted() {
    this.opm('initMap').then(res => {
      console.log(res);
      if (!res) return
      // 加载完地图之后需要获取无线传感网络的位置
      this.toGetSensor();
      // 加载水质区域状态热力图
      this.initHeatData();
    })
    // 绑定获取无人船定位函数
    this.$bus.$on("getPositions", this.getGpsPosition);
    // 绑定生成路线的函数
    this.$bus.$on("buildPlanMarkers", this.buildPlanMarkers);
    this.$bus.$on("stopGetPositions", () => {
      clearInterval(this.timeId);
    });
  },
  beforeDestroy() {
    // 事件解绑
    this.$bus.$off("getPositions");
    this.$bus.$off("buildPlanMarkers");
    this.$bus.$off("stopGetPositions");
    // 定时器关闭
    clearInterval(this.timeId);
  },
  methods: {
    opm(fn, ...args) {
      return this.$refs.zmap[fn](...args)
    },
    // 获取传感器位置并且生成坐标
    async toGetSensor() {
      let { longitude, latitude } = await getSensorLocation();
      this.setSensor([longitude, latitude]);
    },
    // 逆地理编码地址并且存入仓库
    async setSensor(lnglat) {
      let { opm } = this;
      // 写入输入框
      this.sensor.lat = lnglat[1];
      this.sensor.lng = lnglat[0];
      let address = "";
      opm('addMarker', [{
        options: {
          position: lnglat,
          extData: { type: "sensor", MarkerId: 0 },
        },
        icon: 'pink',
        content: '水域4516IAUW812',
        showInfo: true
      }]);
      let circle = opm('addCircle', {
        options: { center: lnglat },
        showInfo: true
      }, 'circleStyle')
      circle.on("click", this.showInfoClick); //添加点击出现信息窗口事件
      address = await opm('useGeocoder', lnglat) || '';
      if (!address) {
        this.$Notify('逆地理编码失败！', 'error');
      }
      // 保存到仓库
      this.$store.commit("cruiseManage/setSensorLocation", {
        longitude: lnglat[0],
        latitude: lnglat[1],
        address,
      });
    },
    // 获取无人船定位
    getGpsPosition() {
      // 启动前先清除一次定时器，以免多按导致开启多个定时器。
      clearInterval(this.timeId);
      this.timeId = setInterval(() => {
        setTimeout(() => {
          getShipPosition()
            .then((res) => {
              // 测试数据
              let empy = {
                longitude: 110.92262732 + a,
                latitude: 21.676619768 + a,
              };
              a += 0.0001
              this.position.lng = empy.longitude.toFixed(6);
              this.position.lat = empy.latitude.toFixed(6);
              this.handleMarker(empy);
              // 真实数据
              // console.log(res);
              // this.position.lng = res.longitude.toFixed(6);
              // this.position.lat = res.latitude.toFixed(6);
              // this.handleMarker(res);
            })
            .catch((err) => {
              console.log(err);
              this.$Notify('定位失败，请稍后再试！', 'error');
              clearInterval(this.timeId);
            });
        }, 0);
      }, 1000);
    },
    // 用经纬度在地图上生成标记与跟随路线
    handleMarker({ longitude, latitude }) {
      let { opm, followPath } = this;
      let zmap = this.$refs.zmap;
      // 获取地图上所有的标记与连线
      const allMarkers = opm('getA_Type', "marker")
      // 获取到代表无人船的标记（MarkerId == 0）
      let oldMarkers = allMarkers.filter(
        (item) =>
          item.getExtData().MarkerId == 0 && item.getExtData().type == "route"
      );
      let Position = [longitude, latitude];
      if (!oldMarkers.length) {
        //说明此时地图没有无人船标记
        followPath = [];
        followPath.push(Position);
        zmap.map.setZoomAndCenter(19, Position);
        opm('addMarker', [{
          options: {
            position: Position,
            zIndex: 99,
            //添加自定义数据0表示无人船标记
            extData: { type: "route", MarkerId: 0 },
          },
          icon: 'red',
          showInfo: true,
          content: `无人船当前坐标:${longitude},${latitude}`
        }])
        this.$Notify('地图中心点已设为无人船位置！');
      } else {
        //说明此时已有无人船标记，获取并且更新位置即可
        oldMarkers[0].setPosition(Position);
        followPath.push(Position); //并且把新数组放入跟随虚线
        const allPolylines = opm('getA_Type', "polyline"); //获取所有的标记
        let FollLine = allPolylines.filter(
          (item) => item.getExtData().lineType === "FollLine"
        );
        if (FollLine.length) zmap.map.remove(FollLine[0]); //删除之前的跟随虚线
        opm('addPolyline', {
          path: followPath,
          extData: { lineType: 'FollLine' }
        }, 'followLineStyle')
      }
    },
    // 水域的信息窗口
    showInfoClick(e) {
      let { opm } = this;
      //构建信息窗体中显示的内容
      var info = [];
      let map = this.$refs.zmap.map;
      info.push("<div class='text-center f-w-600'>水域4516IAUW812</div>");
      info.push("本周警报次数:<b class='f-w-600'>32</b>");
      info.push("异常占比最高:浊度");
      info.push("水质异常程度: <b class='text-c-orange'>一般</b>");
      let infoWindow = opm('getInfoWindow', {
        content: info.join("<br/>"), //使用默认信息窗体框样式，显示信息内容
      })
      infoWindow.open(map, [e.lnglat.KL, e.lnglat.kT]);
    },
    // 生成指定路径标点
    buildPlanMarkers(data) {
      let { opm } = this;
      let map = this.$refs.zmap.map;
      const markers = opm('getA_Type', "marker"); //获取所有的标记
      const allPolylines = opm('getA_Type', "polyline"); //获取所有的标记
      //过滤出路径的标记
      let Pathmarkers = markers.filter(
        (item) =>
          item.getExtData().type == "route" && item.getExtData().MarkerId != 0
      );
      //过滤出无人船的标记
      let ShipMarker = markers.filter(
        (item) =>
          item.getExtData().type == "route" && item.getExtData().MarkerId == 0
      );
      // 过滤出所有的巡航路径折线
      let route = allPolylines.filter(
        (item) => item.getExtData().lineType == "SetLine"
      );
      //如果没有无人船标记，证明都没有获取无人船定位，因为路线的生成需要无人船标记作为起点。
      if (!ShipMarker.length) {
        this.$Notify('必须先获取无人船定位！', 'warning');
        return;
      }
      // 如果已经有路径了，会清除之前的路径标记与折线
      if (Pathmarkers.length) map.remove(Pathmarkers);
      if (route.length) map.remove(route[0]);
      // 开始遍历坐标点进行生成路线
      data.map((item, index) => {
        opm('addMarker', [{
          options: {
            position: [item.lng, item.lat],
            extData: { type: "route", MarkerId: ++index },
          },
          icon: 'I' + index,
          content: `第${index}点坐标为${item.lng},${item.lat}`,
          showInfo: true
        }])
        opm('fitView');
      });
      this.buildPlanLine();
    },
    // 依靠当前地图的标记生成路线
    buildPlanLine() {
      let { opm } = this;
      let map = this.$refs.zmap.map;
      const markers = opm('getA_Type', "marker"); //获取所有的标记
      const allPolylines = opm('getA_Type', "polyline"); //获取所有的标记
      let route = allPolylines.filter(
        (item) => item.getExtData().lineType === "SetLine"
      );
      if (route.length) map.remove(route[0]); //删除之前的折线
      let path = [];
      // 只获取路径标记，并给标记排序
      let Pathmarkers = markers.filter(
        (item) => item.getExtData().type == "route"
      );
      Pathmarkers = Pathmarkers.sort(
        (a, b) => a.getExtData().MarkerId - b.getExtData().MarkerId
      );
      if (Pathmarkers.length > 1) {
        // 按顺序添加作为折线的折点
        Pathmarkers.map((item) => {
          path.push([item._position[0], item._position[1]]);
        });
        // 形成闭环再次添加第一点标记
        path.push([Pathmarkers[1]._position[0], Pathmarkers[1]._position[1]]);
        // 给折线实例设置折线实例的折点
        opm('addPolyline', {
          path,
          extData: { lineType: "SetLine" },
        }, 'polylineStyle')
        this.$Notify('标点与路线已生成！');
      } else {
        //说明当前地图上只有一个点，没法生成路线
        this.$Notify('标点已生成,但当前无法生成路线！', 'warning');
      }
    },
    // 修改无线传感网络
    addDPMarker() {
      let { opm } = this;
      let { lng, lat } = this.sensor;
      const allMarkers = opm('getA_Type', "marker"); //获取所有的标记
      // 获取到代表无线传感网络的标记
      let oldMarkers = allMarkers.filter(
        (item) => item.getExtData().MarkerId == "无线传感网络"
      );
      if (oldMarkers.length) {
        oldMarkers[0].setMap(null);
      } //如果已存在标记就删除
      // 传去做逆地理编码
      this.setSensor([lng, lat]);
      // 修改上传服务器
      let data = {
        id: null,
        latitude: lat,
        longitude: lng,
      };
      updateSensorLocation(data).catch((err) => {
        this.$Notify('添加失败，请稍后再试！', 'error');
      });
      //关闭弹窗
      this.addDpDialog = false;
    },
    // 水质分布数据(热力图)初始化
    initHeatData() {
      let { opm } = this;
      let heatmapOpts = {
        //3d 相关的参数
        '3d': {
          heightBezier: [0.7, 0.2, 0.4, 0.8],
          //取样精度，值越小，曲面效果越精细，但同时性能消耗越大
          gridSize: 2,
          heightScale: 1
        }
      };
      let heatmap = opm('getHeatMap', heatmapOpts)
      heatmap.setDataSet({
        data: this.regionalData,
        max: 100
      });
    },
    // 添加水质分布数据
    addRegional() {
      let data = this.regionalInput;
      let handled = data.filter(item => Object.values(item).every(o => o != ''))
      insertPointQualitys(JSON.stringify(handled)).then(res => {
        console.log(res);
      })
    },
  },
  computed: {
    ...mapState("waterAnalysis", ["regionalData"]),
  }
};
</script>

<style scoped lang="less">
/deep/ .amap-marker,
/deep/ .amap-icon,
/deep/ .amap-icon img {
  width: 32px !important;
  height: 32px !important;
}


.mapView {
  position: relative;

  .map-view {
    height: 580px;
  }

  .lngLatBox {
    position: absolute;
    top: 10px;
    right: 10px;
    width: 220px;
    height: 60px;
    border-radius: 15px;
    padding: 10px;
    background-color: #fff;
    box-shadow: 0 2px 6px 0 rgba(72, 85, 233, 0.8);
  }
}
</style>